MyBatis 您所在的位置:网站首页 sql 动态表名 MyBatis

MyBatis

2024-02-19 03:28| 来源: 网络整理| 查看: 265

一、MyBatis-Plus动态表名插件使用

官方文档-动态表名插件:https://baomidou.com/pages/2a45ff/#dynamictablenameinnerinterceptor

官方有demo,使用起来还是蛮简单的。

1、DynamicTableNameInnerInterceptor插件源码

DynamicTableNameInnerInterceptor:原理为解析替换设定表名为处理器的返回表名,表名建议可以定义复杂一些避免误替换。

重点看 changeTable方法。

TableNameHandler tableNameHandler是一个接口。使用动态表名插件时,必须要有 TableNameHandler的实现类。

在这里插入图片描述

2、使用

模拟使用场景:

一个 entity 对应多张表(多张表结构一致,只有表名称不同),在使用时,可以动态映射表名称。 比如:按照时间分表,某些业务冷热数据分离后数据存在不同的表中等。根据自定义的算法找到我们需要查询的表名。

下面我通过参数的方式传入动态表名来操作。

2.1 请求参数动态表名传递辅助类 /** * 请求参数动态表名传递辅助类 */ public class RequestDynamicTableNameHelper { /** * 请求参数存取(表名)。请求参数自定义,官方Demo定义为ThreadLocal */ private static final ThreadLocal REQUEST_DATA = new ThreadLocal(); /** * 设置请求参数 * * @param requestData * 请求参数-表名 */ public static void setRequestData(String requestData) { REQUEST_DATA.set(requestData); } /** * 获取请求参数 * * @return 请求参数-表名 */ public static String getRequestData() { return REQUEST_DATA.get(); } /** * 移除获取请求参数(表名) */ public static void remove() { REQUEST_DATA.remove(); } } 2.2 注入动态表名插件

MybatisPlusConfig配置中添加动态表名 DynamicTableNameInnerInterceptor插件。

使用多个功能插件时注意顺序关系,官方建议使用如下顺序:

多租户,动态表名分页,乐观锁sql 性能规范,防止全表更新与删除

总结:对 sql 进行单次改造的优先放入,不对 sql 进行改造的最后放入。

@Configuration public class MyBatisPlusConfig { /** * 注册插件 */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); //1.添加动态表名插件 DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor(); dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> { //匿名内部类 String requestTableName = RequestDynamicTableNameHelper.getRequestData(); // 如果不为空,使用动态表名。 if(StringUtils.isNotBlank(requestTableName)){ RequestDynamicTableNameHelper.remove(); return requestTableName; } return tableName; }); interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor); // 2.添加分页插件 PaginationInnerInterceptor pageInterceptor = new PaginationInnerInterceptor(); // 设置数据库方言类型 pageInterceptor.setDbType(DbType.MYSQL); // 下面配置根据需求自行设置 // 设置请求的页面大于最大页后操作,true调回到首页,false继续请求。默认false pageInterceptor.setOverflow(false); // 单页分页条数限制,默认无限制 pageInterceptor.setMaxLimit(500L); interceptor.addInnerInterceptor(pageInterceptor); //3.乐观锁插件 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } } 2.3 service类

创建三个表:

DROP TABLE IF EXISTS `t_dynamic_demo`; CREATE TABLE t_dynamic_demo ( id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名', age INT(11) NULL DEFAULT NULL COMMENT '年龄', email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱', PRIMARY KEY (id) ); DROP TABLE IF EXISTS `t_dynamic_demo_1`; CREATE TABLE t_dynamic_demo_1 ( id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名', age INT(11) NULL DEFAULT NULL COMMENT '年龄', email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱', PRIMARY KEY (id) ); DROP TABLE IF EXISTS `t_dynamic_demo_2`; CREATE TABLE t_dynamic_demo_2 ( id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名', age INT(11) NULL DEFAULT NULL COMMENT '年龄', email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱', PRIMARY KEY (id) );

mapper和实体类与之前的单表写法是一样。这里只需要生成 t_dynamic_demo表的代码即可。

然后在 service类中我们加入 动态表名请求的方法即可。

public interface DynamicDemoService extends IService { void save(String dynamicTableName, DynamicDemoDO dynamicDemoDO); void updateById(String dynamicTableName, DynamicDemoDO dynamicDemoDO); void deleteById(String dynamicTableName, Long id); DynamicDemoDO getById(String dynamicTableName, Long id); } @Service public class DynamicDemoServiceImpl extends ServiceImpl implements DynamicDemoService { @Autowired private DynamicDemoMapper dynamicDemoMapper; @Override public void save(String dynamicTableName, DynamicDemoDO dynamicDemoDO) { //将动态表名放到请求参数中(表名) if(StringUtils.isNotBlank(dynamicTableName)){ RequestDynamicTableNameHelper.setRequestData(dynamicTableName); } //和以前使用一样 dynamicDemoMapper.insert(dynamicDemoDO); } @Override public void updateById(String dynamicTableName, DynamicDemoDO dynamicDemoDO) { if(StringUtils.isNotBlank(dynamicTableName)){ RequestDynamicTableNameHelper.setRequestData(dynamicTableName); } dynamicDemoMapper.updateById(dynamicDemoDO); } @Override public void deleteById(String dynamicTableName, Long id) { if(StringUtils.isNotBlank(dynamicTableName)){ RequestDynamicTableNameHelper.setRequestData(dynamicTableName); } dynamicDemoMapper.deleteById(id); } @Override public DynamicDemoDO getById(String dynamicTableName, Long id) { if(StringUtils.isNotBlank(dynamicTableName)){ RequestDynamicTableNameHelper.setRequestData(dynamicTableName); } return dynamicDemoMapper.selectById(id); } } 2.4 测试类 @Autowired private DynamicDemoService dynamicDemoService; @Test public void testSave(){ DynamicDemoDO dynamicDemoDO = new DynamicDemoDO(); dynamicDemoDO.setName("dynamicDemoDO"); dynamicDemoDO.setAge(18); dynamicDemoDO.setEmail("setEmail 111"); dynamicDemoService.save(dynamicDemoDO); /** * 使用动态表名时,数据库的id自增,同一个请求不能同时插入同一个表的两条记录。 * Duplicate entry '1' for key 't_dynamic_demo.PRIMARY' */ //dynamicDemoService.save(dynamicDemoDO); dynamicDemoDO.setName("dynamicDemoDO_111"); dynamicDemoService.save("t_dynamic_demo_1", dynamicDemoDO); dynamicDemoDO.setName("dynamicDemoDO_222"); dynamicDemoService.save("t_dynamic_demo_2", dynamicDemoDO); } @Test public void testUpdateById(){ DynamicDemoDO dynamicDemoDO = new DynamicDemoDO(); dynamicDemoDO.setId(1L); dynamicDemoDO.setName("dynamicDemoDO_11111_update"); dynamicDemoDO.setEmail("setEmail 111update"); dynamicDemoService.save("t_dynamic_demo_1", dynamicDemoDO); } @Test public void testDeleteById(){ dynamicDemoService.getById("t_dynamic_demo_1", 1L); } @Test public void testGetById(){ DynamicDemoDO t_dynamic_demo_1 = dynamicDemoService.getById("t_dynamic_demo_1", 1L); DynamicDemoDO t_dynamic_demo_2 = dynamicDemoService.getById("t_dynamic_demo_2", 1L); System.out.println("t_dynamic_demo_1 ->" + t_dynamic_demo_1); System.out.println("t_dynamic_demo_2 ->" + t_dynamic_demo_1); }

1)保存 在这里插入图片描述 2)获取 在这里插入图片描述 注意:上面测试时,连续保存两条记录,报错了。但是我在使用下面方式时操作OK的。

@Override public void batchSaveDynamicDemo(String dynamicTableName, UserDO userDO, List dynamicDemoList) { int insert = userMapper.insert(userDO); for (DynamicDemoDO dynamicDemoDO : dynamicDemoList) { if(StringUtils.isNotBlank(dynamicTableName)){ RequestDynamicTableNameHelper.setRequestData(dynamicTableName); } dynamicDemoService.save(dynamicTableName, dynamicDemoDO); } }

– 求知若饥,虚心若愚。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有